package com.fy.fyspace.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fy.fyspace.mapper.ConcurrentTaskMapper;
import com.fy.fyspace.model.entity.ConcurrentTask;
import com.fy.fyspace.service.ConcurrentTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * 并发任务服务实现类
 *
 * @author fwq
 * @since 2025-06-14
 */
@Slf4j
@Service
public class ConcurrentTaskServiceImpl implements ConcurrentTaskService {

    @Resource
    private ConcurrentTaskMapper concurrentTaskMapper;
    
    /**
     * 创建线程池
     * 核心线程数：10
     * 最大线程数：20
     * 队列容量：100
     * 线程存活时间：60秒
     */
    private final ThreadPoolExecutor executorService = new ThreadPoolExecutor(
            10, // 核心线程数
            20, // 最大线程数
            60L, // 线程存活时间
            TimeUnit.SECONDS, // 时间单位
            new LinkedBlockingQueue<>(100), // 工作队列
            new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
    );//电费除以天数，再除以4算出平均每天每个人的，然后在几天就算进去今天就行了

    /**
     * 初始化测试任务
     * 系统启动时自动创建100个测试任务
     */
    @PostConstruct
    public void init() {
        // 检查是否已有任务
        if (concurrentTaskMapper.selectCount(null) > 0) {
            return;
        }
        
        // 创建100个测试任务
        List<ConcurrentTask> tasks = new ArrayList<>();
        for (int i = 1; i <= 100; i++) {
            ConcurrentTask task = new ConcurrentTask();
            task.setName("测试任务" + i);
            task.setStatus(0); // 待处理状态
            tasks.add(task);
        }
        
        // 批量插入任务
        tasks.forEach(concurrentTaskMapper::insert);
        log.info("初始化完成，创建了{}个测试任务", tasks.size());
    }

    /**
     * 批量创建并发任务
     * 使用事务确保数据一致性
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ConcurrentTask> batchCreateTasks(List<String> taskNames) {
        List<ConcurrentTask> tasks = taskNames.stream().map(name -> {
            ConcurrentTask task = new ConcurrentTask();
            task.setName(name);
            task.setStatus(0); // 待处理状态
            return task;
        }).collect(Collectors.toList());
        
        tasks.forEach(concurrentTaskMapper::insert);
        return tasks;
    }

    /**
     * 执行指定任务
     * @param taskId 任务ID
     * @return
     */
    @Override
    public String executeTask(Long taskId) {
        long startTime = System.currentTimeMillis();
        ConcurrentTask task = concurrentTaskMapper.selectById(taskId);
        if (task == null) {
            return "任务不存在";
        }
        
        if (task.getStatus() != 0) {
            return "任务状态不正确，当前状态：" + task.getStatus();
        }
        
        try {
            // 更新任务状态为处理中
            task.setStatus(1);
            concurrentTaskMapper.updateById(task);
            
            // 模拟任务执行耗时（随机1-2.5秒）
            Thread.sleep(1000 + (long)(Math.random() * 1500));
            
            // 更新任务状态为完成
            task.setStatus(2);
            concurrentTaskMapper.updateById(task);
            
            long endTime = System.currentTimeMillis();
            log.info("任务 {} 执行完成，耗时：{}ms", task.getName(), (endTime - startTime));
            return String.format("任务执行成功，耗时：%dms", (endTime - startTime));
        } catch (Exception e) {
            log.error("任务执行异常", e);
            // 发生异常时更新任务状态为失败
            task.setStatus(3);
            concurrentTaskMapper.updateById(task);
            return "任务执行失败：" + e.getMessage();
        }
    }

    /**
     * 并行执行所有待处理任务
     * @return
     */
    @Override
    public String executeTasks() {
        long startTime = System.currentTimeMillis();
        
        // 查询所有待处理的任务
        LambdaQueryWrapper<ConcurrentTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ConcurrentTask::getStatus, 0);
        List<ConcurrentTask> tasks = concurrentTaskMapper.selectList(wrapper);
        
        if (tasks.isEmpty()) {
            return "没有待处理的任务";
        }
        
        log.info("开始执行{}个任务，当前线程池状态：活跃线程数={}，队列大小={}，已完成任务数={}",
                tasks.size(),
                executorService.getActiveCount(),
                executorService.getQueue().size(),
                executorService.getCompletedTaskCount());
        
        List<CompletableFuture<Void>> futures = new ArrayList<>();
        
        // 并发执行任务
        for (ConcurrentTask task : tasks) {
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    // 更新任务状态为处理中
                    task.setStatus(1);
                    concurrentTaskMapper.updateById(task);
                    
                    // 模拟任务执行耗时（随机1-2.5秒）
                    Thread.sleep(1000 + (long)(Math.random() * 1500));
                    
                    // 更新任务状态为完成
                    task.setStatus(2);
                    concurrentTaskMapper.updateById(task);
                    
                    log.info("任务 {} 执行完成", task.getName());
                } catch (Exception e) {
                    log.error("任务执行异常", e);
                    // 发生异常时更新任务状态为失败
                    task.setStatus(3);
                    concurrentTaskMapper.updateById(task);
                }
            }, executorService);
            
            futures.add(future);
        }
        
        // 等待所有任务完成
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        
        long endTime = System.currentTimeMillis();
        long totalTime = endTime - startTime;
        
        // 计算理论串行执行时间（假设每个任务平均1.75秒）
        long theoreticalTime = tasks.size() * 1750;
        
        String result = String.format("共执行 %d 个任务，总耗时：%dms，理论串行耗时：%dms，性能提升：%.2f倍",
                tasks.size(),
                totalTime,
                theoreticalTime,
                (double) theoreticalTime / totalTime);
        
        log.info(result);
        return result;
    }

    /**
     * 串行执行所有待处理任务
     * @return
     */
    @Override
    public String executeTasksSequentially() {
        long startTime = System.currentTimeMillis();
        
        // 查询所有待处理的任务
        LambdaQueryWrapper<ConcurrentTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ConcurrentTask::getStatus, 0);
        List<ConcurrentTask> tasks = concurrentTaskMapper.selectList(wrapper);
        
        if (tasks.isEmpty()) {
            return "没有待处理的任务";
        }
        
        log.info("开始串行执行{}个任务", tasks.size());
        
        // 串行执行任务
        for (ConcurrentTask task : tasks) {
            try {
                // 更新任务状态为处理中
                task.setStatus(1);
                concurrentTaskMapper.updateById(task);
                
                // 模拟任务执行耗时（随机1-2.5秒）
                Thread.sleep(1000 + (long)(Math.random() * 1500));
                
                // 更新任务状态为完成
                task.setStatus(2);
                concurrentTaskMapper.updateById(task);
                
                log.info("任务 {} 执行完成", task.getName());
            } catch (Exception e) {
                log.error("任务执行异常", e);
                // 发生异常时更新任务状态为失败
                task.setStatus(3);
                concurrentTaskMapper.updateById(task);
            }
        }
        
        long endTime = System.currentTimeMillis();
        long totalTime = endTime - startTime;
        
        String result = String.format("串行执行完成，共执行 %d 个任务，总耗时：%dms",
                tasks.size(),
                totalTime);
        
        log.info(result);
        return result;
    }

    /**
     * 查询所有任务
     * @return
     */
    @Override
    public List<ConcurrentTask> listAllTasks() {
        return concurrentTaskMapper.selectList(null);
    }
} 